﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel.Syndication;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using Cofe.Core.Logger;

namespace Cofe.Web.Feed
{
    public class Feed<T> : IFeed
        where T : EventArgs
    {
  
        #region Constructor

        public Feed(FeedId fid, SyndicationFeed innerFeed, IFeedBuilder<T> feedBuilder)
        {
            FeedId = fid;
            _innerFeed = innerFeed;
            _feedBuilder = feedBuilder;
        }
        

        public static Feed<T> FromFeedId(FeedId feedId, IFeedBuilder<T> feedBuilder)
        {
           return new Feed<T>(feedId, null, feedBuilder);            
        }

        public static Feed<T> FromFileName(FeedDirectory feedDirectory, string fileName, IFeedBuilder<T> feedBuilder)
        {
            var innerFeed = getInnerFeed(feedDirectory, fileName);
            var feedId = FeedId.FromUrl(innerFeed.GetViaLink().Uri, fileName, feedBuilder);
            return new Feed<T>(feedId, innerFeed, feedBuilder);
        }

        #endregion

        #region Methods

        private static SyndicationFeed getInnerFeed(FeedId id)
        {
            return getInnerFeed(id.FeedDirectory, id.FileName);
        }

        private static SyndicationFeed getInnerFeed(FeedDirectory feedDirectory, string fileName)
        {
            SyndicationFeed innerFeed;
            

            using (XmlReader reader = CofeWsServices.Feeds.GetFeedService<T>().
                           FileSystem.GetXmlReader(feedDirectory, fileName))
            {
                innerFeed = SyndicationFeed.Load(reader);
            }
            return innerFeed;
        }

        public bool IsFull() {

            if (FeedId.FeedType != FeedType.RecentEventFeed)
                throw new NotSupportedException();
            return InnerFeed.Items.Count() >= CofeWsServices.CofeWsSettings.FeedQuota; }

        public void AddEvent(IEventLog<T> eventLog)
        {
            var newEntry = _feedBuilder.BuildEntry(eventLog);
            newEntry.AddTo(InnerFeed);
            newEntry.Save();
        }

        public void Save()
        {            
            using (XmlWriter writer =  CofeWsServices.Feeds.GetFeedService<T>().
                FileSystem.GetXmlWriter(FeedId.FeedDirectory, FeedId.FileName))
            {
                InnerFeed.GetAtom10Formatter().WriteTo(writer);
            }
        }

        #endregion

        #region Data

        IFeedBuilder<T> _feedBuilder;
        SyndicationFeed _innerFeed = null;

        #endregion

        #region Public Properties


        public FeedId FeedId { get; private set; }
        public string ETag { get { return CofeWsServices.Feeds.GetFeedService<T>().FileSystem.GetETag(FeedId); } }
        public bool IsExists { get { return CofeWsServices.Feeds.GetFeedService<T>().
                           FileSystem.IsExists(FeedId.FeedDirectory, FeedId.FileName); } }                
        public SyndicationFeed InnerFeed
        {
            get { return _innerFeed ?? (_innerFeed = getInnerFeed(FeedId)); }
        }

        #endregion
        
    }
}
